#include "scheduler_rts.h"

Scheduler_RTS :: Scheduler_RTS (bool is_soft) {
	soft = is_soft;
	//Vectors shouldn't need further initialization
	clock = 0;	
	available = new list <Process> ();
	skipped = new list <string> ();
	ran = new list <string> ();
	clock = 0;
}

Scheduler_RTS :: ~Scheduler_RTS () {
	processes.erase(processes.begin(), processes.end());
	available.erase(available.begin(), available.end());
	skipped.erase(skipped.begin(), skipped.end());
	ran.erase(ran.begin(), ran.end());
}

void Scheduler_RTS :: begin (list <Process> * processes) {
	cout << "Running the RTS scheduler" << endl;
	cout << "Hard RTS Simulation" << endl;
	run_hard_RTS();
	cout << "Soft RTS Simulation" << endl;
	run_soft_RTS();
}

void Scheduler_RTS :: run_hard_RTS() {
	cout << "runHardRTS called" << endl;
	if(processes.empty()) {
		cout << "ERROR in runHardRTS - No Processes in scheduler!" << endl;
	} else {
		find_available_processes(clock);
	}

	while(!processes.empty()) {
		//cleanProcesses();
		find_available_processes(clock);
		if(!available.empty()) {
			//Collections.sort(available);
			available.front().run_for(1);
			ran.push_back(available.front().get_pid());
		} else {
			ran.push_back("--");
		}

		clock++;
	}

	if(!ran.empty()) {
		print_gantt();
	}
}

void Scheduler_RTS :: run_soft_RTS() {
	cout << "runSoftRTS called...FINISH" << endl;
}

void Scheduler_RTS :: find_skipped_processes(int clk) {
	cout << "findSkippedProcesses(" << clk << ") called...FINISH" << endl;

	vector<Process>::iterator itr;
	for(itr = processes.begin(); itr < processes.end(); itr++) {
		//Check to see that skipped doesn't contain *itr
		if((itr -> get_arrival() <= clk) && (itr -> get_t_remain() > 0) && (itr -> get_deadline() < clk)) {
			skipped.push_back(itr -> get_pid());
		}
	}
}

void Scheduler_RTS :: find_available_processes(int clk) {
   cout << "findAvailableProcesses(" << clk << ") called...FINISH" << endl;

	vector<Process>::iterator itr;
	for(itr = processes.begin(); itr < processes.end(); itr++) {
		//Check to see that available or skipped don't contain *itr
		if((itr -> get_arrival() <= clk) && (itr -> get_t_remain() > 0)) {
			available.push_back(*itr);
		}
	}
}

void Scheduler_RTS :: print_gantt() {
   cout << "---Gantt Chart---\n" << "0";
	   string previous = "";

		for(int i = 0; i < (int)ran.size(); i++) {
	      if(i < (int)ran.size()) {
	         if(ran.at(i) != previous) {
	            if(!previous.empty()) {
	               cout << " [" << previous << "] " << i;
	            }
	            previous = ran.at(i);
	         }
	      } else if(ran.at(i - 1) == previous) {
	         cout << " [" << previous << "] " << i;
	      } else {
	         cout << " [" << ran.at(i - 1) << "] " << i;
	      }
	   }

	   cout << endl;
}

// Outputs a Gantt chart in the form "0 [PID1] 2 [PID2] 5"
void Generic_Scheduler :: show_gantt () {
	cout << "Scheduler::show_gantt() called...FINISH" << endl;
}
